package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.model.qo.QueryCourseBaseModel;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseChargeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.CourseMarketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 课程基本信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase> implements CourseBaseService {


    // 为了考虑到业务操作后数据，应该使用service
    @Autowired
    private CourseMarketService courseMarketService;


    @Transactional
    public Map<String, Object> previewCourse(Long courseId, Long companyId) {
        return null;
    }


    public PageVO queryCourseList(PageRequestParams params, QueryCourseBaseModel model,Long companyId) {

        //1.判断关键数据
        if (params.getPageNo() < 0) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if (params.getPageSize() < 0) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }
        // 2. 创建分页数据
        Page<CourseBase> basePage = new Page<>(params.getPageNo(),params.getPageSize());
        // 3.构建查询条件
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        String courseName = model.getCourseName();
        String auditStatus = model.getAuditStatus();
        queryWrapper.like(!(StringUtil.isBlank(courseName)),CourseBase::getName, courseName);
        queryWrapper.eq(!(StringUtil.isBlank(auditStatus)),CourseBase::getAuditStatus, auditStatus);
        // 添加公司的id值来实现教学机构的数据隔离
        queryWrapper.eq(!(ObjectUtils.isEmpty(companyId)),CourseBase::getCompanyId, companyId);
        // 4.查询数据
        Page<CourseBase> pageResult = this.page(basePage, queryWrapper);
        List<CourseBase> records = pageResult.getRecords();
        long total = pageResult.getTotal();
        List<CourseBaseDTO> dtos = Collections.EMPTY_LIST;
        if (!(CollectionUtils.isEmpty(records))) {
            dtos = CourseBaseConvert.INSTANCE.entitys2dtos(records);
        }
        // 5.将数据封装到PageVO
        PageVO<CourseBaseDTO> pageVO = new PageVO(dtos,total,params.getPageNo(),params.getPageSize());
        // 6.返回结果
        return pageVO;
    }
    @Transactional
    public CourseBaseDTO createCourseBase(CourseBaseDTO dto) {
        verifyCourseMsg(dto);
        // 3.保存课程数据
        CourseBase courseBase = CourseBaseConvert.INSTANCE.dto2entity(dto);
        // 给课程基本信息赋值默认审核状态：未提交
        courseBase.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());
        // 保存成功后，mybatis会将id值回显到对象中
        boolean baseResult = this.save(courseBase);
        if (!baseResult) {
            throw new RuntimeException("保存课程数据失败");
        }
        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setCourseId(courseBase.getId());
        courseMarket.setCharge(dto.getCharge());
        String charge = dto.getCharge();
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(charge)) {
            BigDecimal price = dto.getPrice();
            if (ObjectUtils.isEmpty(price)) {
                throw new RuntimeException("收费课程必须要有价格");
            }
            courseMarket.setPrice(dto.getPrice().floatValue());
        }
        boolean marketResult = courseMarketService.save(courseMarket);
        if (!marketResult) {
            throw new RuntimeException("保存课程营销数据失败");
        }

        // 4.将数据库最新的数据转为dto并返回
        CourseBase po = this.getById(courseBase.getId());

        CourseBaseDTO resultDTO = CourseBaseConvert.INSTANCE.entity2dto(po);

        resultDTO.setPrice(dto.getPrice());
        resultDTO.setCharge(dto.getCharge());


        return resultDTO;
    }



    private void verifyCourseMsg(CourseBaseDTO dto) {
        //2.判断关键数据
        if (ObjectUtils.isEmpty(dto.getCompanyId())) {
            ExceptionCast.cast(CommonErrorCode.E_403000);
        }
        if (StringUtil.isBlank(dto.getName())) {
            ExceptionCast.cast(ContentErrorCode.E_120004);
        }

        if (StringUtil.isBlank(dto.getMt())) {
            ExceptionCast.cast(ContentErrorCode.E_120002);
        }

        if (StringUtil.isBlank(dto.getSt())) {
            ExceptionCast.cast(ContentErrorCode.E_120003);
        }

        if (StringUtil.isBlank(dto.getGrade())) {
            ExceptionCast.cast(ContentErrorCode.E_120007);
        }

        if (StringUtil.isBlank(dto.getTeachmode())) {
            ExceptionCast.cast(ContentErrorCode.E_120006);
        }

        if (StringUtil.isBlank(dto.getUsers())) {
            ExceptionCast.cast(ContentErrorCode.E_120019);
            throw new RuntimeException("使用人群不能为空");
        }

        if (StringUtil.isBlank(dto.getCharge())) {
            ExceptionCast.cast(ContentErrorCode.E_120020);
            throw new RuntimeException("课程收费不能为空");
        }
    }

    public CourseBaseDTO getCourseBaseById(Long courseBaseId, Long companyId) {

        //1.判断关键数据
        //     courseBaseId  companyId
        if (ObjectUtils.isEmpty(courseBaseId)||
                ObjectUtils.isEmpty(companyId)
        ) {
           ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        // 2.判断业务数据
        LambdaQueryWrapper<CourseBase> baseQueryWrapper = new LambdaQueryWrapper<>();
        baseQueryWrapper.eq(CourseBase::getId, courseBaseId);
        baseQueryWrapper.eq(CourseBase::getCompanyId, companyId);
        baseQueryWrapper.eq(CourseBase::getStatus, CommonEnum.USING_FLAG.getCodeInt());
        CourseBase courseBase = this.getOne(baseQueryWrapper);
        if (ObjectUtils.isEmpty(courseBase)) {
            throw new RuntimeException("课程基本信息不存在");
        }
        LambdaQueryWrapper<CourseMarket> marketQueryWrapper = new LambdaQueryWrapper<>();
        marketQueryWrapper.eq(CourseMarket::getCourseId, courseBaseId);

        CourseMarket courseMarket = courseMarketService.getOne(marketQueryWrapper);

        if (ObjectUtils.isEmpty(courseMarket)) {
            throw new RuntimeException("课程营销数据不存在");
        }
        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.entity2dto(courseBase);

        String charge = courseMarket.getCharge();
        courseBaseDTO.setCharge(charge);
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(charge)) {
            Float price = courseMarket.getPrice();
            courseBaseDTO.setPrice(new BigDecimal(price.toString()));
        }

        return courseBaseDTO;
    }

    @Transactional
    public CourseBaseDTO modifyCourseBase(CourseBaseDTO dto, Long companyId) {

        // 1.判断关键数据
        verifyCourseMsg(dto);
        Long courseBaseId = dto.getCourseBaseId();
        if (ObjectUtils.isEmpty(courseBaseId)) {
            throw new RuntimeException("修改课程时id不能为空");
        }
        LambdaQueryWrapper<CourseBase> courseBaseQueryWrapper = new LambdaQueryWrapper<>();

        courseBaseQueryWrapper.eq(CourseBase::getId, courseBaseId);
        courseBaseQueryWrapper.eq(CourseBase::getCompanyId, companyId);

        CourseBase courseBase = this.getOne(courseBaseQueryWrapper);

        if (ObjectUtils.isEmpty(courseBase)) {
            throw new RuntimeException("课程基本信息不存在");
        }

        Integer status = courseBase.getStatus();
        if (CommonEnum.DELETE_FLAG.getCodeInt().equals(status)) {
            throw new RuntimeException("课程基本信息已删除");
        }

        String auditStatus = courseBase.getAuditStatus();

        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            throw new RuntimeException("课程审核状态异常");
        }
        LambdaQueryWrapper<CourseMarket> marketQueryWrapper = new LambdaQueryWrapper<>();
        marketQueryWrapper.eq(CourseMarket::getCourseId, courseBaseId);

        int count = courseMarketService.count(marketQueryWrapper);
        if (count <1) {
            throw new RuntimeException("课程营销数据不存在");
        }

        CourseBase po = CourseBaseConvert.INSTANCE.dto2entity(dto);

        po.setId(courseBase.getId());
        po.setAuditStatus(courseBase.getAuditStatus());
        po.setStatus(courseBase.getStatus());
        po.setCompanyId(courseBase.getCompanyId());

        boolean baseResult = this.updateById(po);

        if (!baseResult) {
            throw new RuntimeException("修改课程基本信息失败");
        }

        LambdaUpdateWrapper<CourseMarket> marketUpdateWrapper = new LambdaUpdateWrapper<>();
        String charge = dto.getCharge();
        marketUpdateWrapper.set(CourseMarket::getCharge, charge);
        // 如果课程是收费课程，必须要给price赋值
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(charge)) {
            if (ObjectUtils.isEmpty(dto.getPrice())) {
                throw new RuntimeException("收费课程必须要有价格");
            }

            marketUpdateWrapper.set(CourseMarket::getPrice,dto.getPrice());
        }

        marketUpdateWrapper.eq(CourseMarket::getCourseId, courseBaseId);
        boolean marketResult = courseMarketService.update(marketUpdateWrapper);
        if (!marketResult) {
            throw new RuntimeException("修改课程营销信息失败");
        }


        //  4.将数据库最新的数据转为dto返回给前端

        CourseBase base = this.getById(courseBaseId);
        CourseBaseDTO resultDTO = CourseBaseConvert.INSTANCE.entity2dto(base);
        resultDTO.setPrice(dto.getPrice());
        resultDTO.setCharge(dto.getCharge());

        return resultDTO;
    }

    @Transactional
    public void commitCourseBase(Long courseId, Long companyId) {

        //1.判断关键数据
        if (ObjectUtils.isEmpty(courseId)||
                ObjectUtils.isEmpty(companyId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 2.判断业务数据
        CourseBaseDTO courseBase = this.getCourseBaseById(courseId, companyId);

        String auditStatus = courseBase.getAuditStatus();

        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }
        // 3.修改课程的审核状态
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getAuditStatus,CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode() );
        updateWrapper.set(CourseBase::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(CourseBase::getId,courseBase.getCourseBaseId() );

        boolean result = this.update(updateWrapper);

        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }
    }

    @Transactional
    public void approveCourse(CourseBaseDTO dto) {

        //1.判断关键数据
        String auditStatus = dto.getAuditStatus();
        if (ObjectUtils.isEmpty(dto.getCourseBaseId())||
                StringUtil.isBlank(auditStatus)||
                StringUtil.isBlank(dto.getAuditMind())
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }
        // 判断审核的数据
        if (CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode().equals(auditStatus)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120016);
        }
        // 2.判断业务数据
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseBase::getId, dto.getCourseBaseId());
        queryWrapper.eq(CourseBase::getStatus, CommonEnum.USING_FLAG.getCodeInt());
        queryWrapper.eq(CourseBase::getAuditStatus, CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode());

        int count = this.count(queryWrapper);
        if (count < 1) {
            ExceptionCast.cast(ContentErrorCode.E_120021);
        }


        // 3.修改课程基本信息数据
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();

        updateWrapper.set(CourseBase::getAuditMind, dto.getAuditMind());
        updateWrapper.set(CourseBase::getAuditStatus, dto.getAuditStatus());
        updateWrapper.set(CourseBase::getChangeDate, LocalDateTime.now());
        // updateWrapper.set(CourseBase::getAuditNums, );
        updateWrapper.eq(CourseBase::getId, dto.getCourseBaseId());
        boolean result = this.update(updateWrapper);
        // 4.判断修改后的结果
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }

    }


}
